﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ParallelRuntimeLibrary.Internal;
using ParallelRuntimeLibrary.Collections;

namespace ParallelRuntimeLibrary.Internal
{
    /// <summary>
    /// Represend thread-safe first-in, first-out collection of object.
    /// </summary>
    public class LockedQueue<T>
    {
        private SingleLinkedListNode<T> mHead, mTail;

        /*////////////////////////////////////////////////////////////////////////////////////////////////*/

        #region Class Constructor


        /// <summary>
        /// Initializes a new instance of this class
        /// </summary>
        public LockedQueue()
        {
            mHead = null;
            mTail = null;
        }

        #endregion

        /*////////////////////////////////////////////////////////////////////////////////////////////////*/

        #region Queue Operations

        public void Enqueue(T value)
        {
            SingleLinkedListNode<T> tmp = new SingleLinkedListNode<T>(value);
           
            #region Lock

                lock (this)
                {
                    if (mHead == null)
                        mHead = tmp;
                    else
                        mTail.mNext = tmp;
                    
                    mTail = tmp;
                }

            #endregion
           
        }

        public bool Dequeue(out T value)
        {
            #region Lock

            if (mHead == null)
            {
                value = default(T);
                return false;
            }

                lock (this)
                {
                    if (mHead != null)
                    {
                        value = mHead.mValue;
                        mHead = mHead.mNext;
                        return true;
                    }
                    else
                    {
                        value = default(T);
                        return false;
                    }
                }

                #endregion
        }

        public bool Peek(out T value)
        {
            SingleLinkedListNode<T> tmp = mHead;
            if (tmp != null)
            {
                value = tmp.mValue;
                return true;
            }
            else
            {
                value = default(T);
                return false;
            }
        }

        #endregion


    }

    
}
